#include "random.h"

inline unsigned long twiddle(unsigned long u, unsigned long v)
{
  return (((u & 0x80000000UL) | (v & 0x7FFFFFFFUL)) >> 1)
    ^ ((v & 1UL) ? 0x9908B0DFUL : 0x0UL);
}


void RandomNumberGenerator::seed(unsigned long s)
{  // init by 32 bit seed
  state[0] = s & 0xFFFFFFFFUL; // for > 32 bit machines
  for (int i = 1; i < n; ++i) {
    state[i] = 1812433253UL * (state[i - 1] ^ (state[i - 1] >> 30)) + i;
// see Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier
// in the previous versions, MSBs of the seed affect only MSBs of the array state
// 2002/01/09 modified by Makoto Matsumoto
    state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
  }
  p = n; // force gen_state() to be called for next random number
}


unsigned long RandomNumberGenerator::operator()() 
{ // generate 32 bit random int
  if (p == n) // new state vector needed
  { // generate new state vector
	  for (int i = 0; i < (n - m); ++i)
	    state[i] = state[i + m] ^ twiddle(state[i], state[i + 1]);
	  for (int i = n - m; i < (n - 1); ++i)
	    state[i] = state[i + m - n] ^ twiddle(state[i], state[i + 1]);
	  state[n - 1] = state[m - 1] ^ twiddle(state[n - 1], state[0]);
	  p = 0; // reset position
	}

// gen_state() is split off to be non-inline, because it is only called once
// in every 624 calls and otherwise irand() would become too big to get inlined
  unsigned long x = state[p++];
  x ^= (x >> 11);
  x ^= (x << 7) & 0x9D2C5680UL;
  x ^= (x << 15) & 0xEFC60000UL;
  return x ^ (x >> 18);
}

RandomNumberGenerator RNG;
